package coupon

import (
	"context"

	"mall/common/globalkey"
	enum "mall/service/backend/common/enum/promotion"
	"mall/service/backend/common/errorx"
	"mall/service/backend/common/i18n"
	"mall/service/promotion/model"
	"mall/service/promotion/rpc/internal/svc"
	"mall/service/promotion/rpc/internal/utils/errorhandler"
	"mall/service/promotion/rpc/types/promotion"

	"github.com/zeromicro/go-zero/core/logx"
)

type BackendCreateCouponProductCategoryLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendCreateCouponProductCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendCreateCouponProductCategoryLogic {
	return &BackendCreateCouponProductCategoryLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BackendCreateCouponProductCategoryLogic) BackendCreateCouponProductCategory(
	in *promotion.CouponRelationshipInfo,
) (*promotion.BaseResp, error) {
	if in.TemplateId == 0 {
		return nil, errorx.NewInvalidArgumentError(i18n.ValidationError)
	}

	data, err := l.svcCtx.CouponTemplate.FindOneNoCache(l.ctx, nil, in.TemplateId)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	if data.Status != uint16(globalkey.StatusPending) && data.Status != uint16(globalkey.StatusRejected) {
		return nil, errorx.NewInvalidArgumentError(i18n.ConstraintError)
	}

	if len(in.CategoryIds) > 0 {
		var cids []any
		for _, cid := range in.CategoryIds {
			if cid > 0 {
				cids = append(cids, cid)
			}
		}

		if len(cids) == 0 {
			return nil, errorx.NewInvalidArgumentError(i18n.ValidationError)
		}

		filterMap := make(map[string]map[string][]any)
		filterMap[model.PromotionCouponProductCategoryRelationshipColumns.CouponID] = map[string][]any{
			"equalTo": []any{data.ID},
		}
		filterMap[model.PromotionCouponProductCategoryRelationshipColumns.Status] = map[string][]any{
			"equalTo": []any{globalkey.StatusEnabled},
		}
		filterMap[model.PromotionCouponProductCategoryRelationshipColumns.ProductCategoryID] = map[string][]any{
			"in": cids,
		}
		rel, _, err := l.svcCtx.CouponTemplate.GetProductCategoryList(l.ctx, model.M{}, -1, filterMap)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		cidMap := make(map[uint64]struct{})
		if len(rel) > 0 {
			for _, v := range rel {
				cidMap[v.ProductCategoryID] = struct{}{}
			}
		}

		tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
		if err != nil {
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		bindRel := &model.PromotionCouponBindRel{}
		for idx, cid := range in.CategoryIds {
			if cid == 0 {
				continue
			}

			if _, ok := cidMap[cid]; ok { // 已存在
				continue
			}

			var rel model.PromotionCouponProductCategoryRelationship
			rel.CouponID = data.ID
			rel.ProductCategoryID = cid
			rel.Sort = uint16(idx + 1)
			rel.Status = uint8(globalkey.StatusEnabled)

			bindRel.Categories = append(bindRel.Categories, &rel)
		}

		err = l.svcCtx.CouponTemplate.UpdateBindRel(l.ctx, tx, data.ID, bindRel)
		if err != nil {
			tx.Rollback()
			return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
		}

		var step uint8 = enum.PromotionActivityStepMain
		if step > data.CreateStep {
			data.CreateStep = step
			err = l.svcCtx.CouponTemplate.Update(l.ctx, tx, data, nil)
			if err != nil {
				tx.Rollback()
				return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
			}
		}

		tx.Commit()
	}

	return &promotion.BaseResp{
		Msg: i18n.CreateSuccess,
	}, nil
}
